package com.lancer.cloud.engine.aspect;

import com.lancer.cloud.engine.entity.EngineMonitorLog;
import com.lancer.cloud.engine.service.EngineLogService;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * 监控代理处理类
 *
 * @author caijinbang
 * @date 2019-06-22 16:50
 */
public class MonitorProxyHandler implements InvocationHandler {

    private Object subject;

    private Object[] extraArgs;

    @Autowired
    private EngineLogService engineLogService;

    public MonitorProxyHandler(Object subject){
        this(subject, new Object[]{});
    }

    public MonitorProxyHandler(Object subject, Object[] extraArgs) {
        this.subject = subject;
        this.extraArgs = extraArgs;
    }


    /**
     *
     * @param proxy
     * @param method
     * @param args
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        long start = System.currentTimeMillis();
        EngineMonitorLog log = null;
        Object obj = null;
        //
        if(subject instanceof IRuleCheck) {
            //规则检查
            if(!DO_CHECK.equals(method.getName())) {
                return method.invoke(subject, args);
            }
            RuleCheckContext context = (RuleCheckContext)extraArgs[0];
            RuleConfig config = (RuleConfig)extraArgs[1];
            log = EngineLogUtils.buildEngineMonitorLog(context, config);
            ImplTypeEnum implType = ImplTypeEnum.getImplType(config.getImplType(), ImplTypeEnum.JAVA);
            log.setImplType(implType.name());
            log.setMonitorInterface(IRuleCheck.class.getSimpleName());
            if (subject instanceof RuleCheckVerify) {
                RuleCheckVerify verify = (RuleCheckVerify) subject;
                log.setMonitorCls((verify.getRuleCheck() == null ?
                    subject.getClass().getName() : verify.getRuleCheck().getClass().getName())
                    + "[" + config.getCode() + "]");
            } else {
                log.setMonitorCls(subject.getClass().getName());
            }
            if(implType == ImplTypeEnum.EXPRESSION) {
                log.setScript(config.getParamByEnum(RuleParamsMapEnum.EXPRESSIONSHOW));
            }else{
                log.setScript(config.getParamByEnum(RuleParamsMapEnum.IMPLCONTENT));
            }
            obj = method.invoke(subject, args);
            RuleCheckResult result = (RuleCheckResult)obj;
            log.setCheckStatus(result.isSuccess() ? Constant.ONE : Constant.ZERO);
            log.setCheckResult(JSONUtils.objectToString(result));
            //违规仅提示、干预处理
            CheckResultHandler.postHandle(context, result);
            log.setFinalStatus(result.isSuccess() ? Constant.ONE : Constant.ZERO);
            log.setFinalResult(JSONUtils.objectToString(result));
        }else if(subject instanceof IRuleCheckContext) {
            //上下文
            RuleCheckContext context = (RuleCheckContext)args[0];
            log = EngineLogUtils.buildEngineMonitorLog(context, null);
            log.setMonitorInterface(IRuleCheckContext.class.getSimpleName());
            log.setMonitorCls(subject.getClass().getName());
            log.setImplType(ImplTypeEnum.JAVA.name());
            log.setScript(log.getMonitorCls());
            obj = method.invoke(subject, args);
            if(obj != null) {
                log.setFinalResult(JSONUtils.objectToString(obj));
            }
        }
        if(log != null) {
            log.setRunTime(System.currentTimeMillis() - start);
            engineLogService.insertMonitorLog(log);
        }
        return obj;
    }
}
